#include "VGQLeftSeries.h"
#include <math.h>
#include <boost\math\special_functions\factorials.hpp>

VGQLeftSeries::VGQLeftSeries( double mu, double lambda, double alpha, double beta )
	: VGQRecyclingSeries(mu, lambda, alpha, beta)
{
	_pL = _zeroQuantileLocation;
}

VGQLeftSeries::VGQLeftSeries( std::shared_ptr<VarianceGammaDistribution > pvgDistribution )
	: VGQRecyclingSeries(pvgDistribution)
{
	_pL = _zeroQuantileLocation;
}


VGQLeftSeries::~VGQLeftSeries(void)
{
}

double VGQLeftSeries::baseQuantile( double u )
{
	return _const2 * log(u/_pL);
}

double VGQLeftSeries::q( unsigned int n )
{
	using namespace boost::math;

	size_t size = _vq.size();

	if(n < size)
		return _vq[n];

	if(n == 0){
		_vq.push_back(0.0);
		return _vq[n];
	}

	double sum = 0.0;
	for(size_t k = 0; k < n; k++){
		sum += ((pow(_alpha + _beta, int(k)) * h(n-k-1)) / factorial<double>(k));
	}
	
	_vq.resize(n + 1, 0.0);
	_vq[n] = _const1 * (1/double(n)) * sum;

	return _vq[n];
}

void VGQLeftSeries::SetInitialCondition( double u )
{
	clearCache();

	_u0 = u;
	_x0 = _pvgDistribution->quantile(_u0);
	_const2 = (1/(_alpha + _beta));
	_z0 = baseQuantile(_u0);
	_const1 = _pL * (_alpha + _beta) * exp((_alpha + _beta) * _z0);
	
}

